using System;
using System.Collections.Generic;
using System.Configuration;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Web.Security;
using System.Text;

namespace SubSonicRoles
{
    public abstract class RoleProviderBase : RoleProvider
    {
        //
        // Global connection string, generic exception message, event log info.
        //

        private string eventSource = "LlblGenRoleProvider";
        private string eventLog = "Application";
        private string exceptionMessage = "An exception occurred. Please check the Event Log.";

        private ConnectionStringSettings pConnectionStringSettings;

        private string pApplicationName;
        private int pApplicationId;
        private string pConnectionString;

        public string ConnectionString
        {
            get { return pConnectionString; }
            set { pConnectionString = value; }
        }



        //
        // If false, exceptions are thrown to the caller. If true,
        // exceptions are written to the event log.
        //

        private bool pWriteExceptionsToEventLog = false;

        public bool WriteExceptionsToEventLog
        {
            get { return pWriteExceptionsToEventLog; }
            set { pWriteExceptionsToEventLog = value; }
        }

        //
        // System.Web.Security.RoleProvider properties.
        //


        public override string ApplicationName
        {
            get { return pApplicationName; }
            set { pApplicationName = value; }
        }
        protected int ApplicationId
        {
            get {
                if (pApplicationId == 0)
                    pApplicationId = GetApplicationId(ApplicationName);
                return pApplicationId; 
            }
            set { pApplicationId = value; }
        }
        #region Initialize

        //
        // System.Configuration.Provider.ProviderBase.Initialize Method
        //

        public override void Initialize(string name, NameValueCollection config)
        {

            //
            // Initialize values from web.config.
            //

            if (config == null)
                throw new ArgumentNullException("config");

            if (name == null || name.Length == 0)
                name = "LlblGenRoleProvider";

            if (String.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "Role provider using LLBLGen Pro ORMapper");
            }

            // Initialize the abstract base class.
            base.Initialize(name, config);

            pConnectionStringSettings = ConfigurationManager.
             ConnectionStrings[config["connectionStringName"]];

            if (pConnectionStringSettings != null && pConnectionStringSettings.ConnectionString.Trim() != "")
            {
                //If a connection string is specified then use it, otherwise LLBL will use the 
                //one in Main.ConnectionString app setting
                ConnectionString = pConnectionStringSettings.ConnectionString;
            }


            if (config["applicationName"] == null || config["applicationName"].Trim() == "")
            {
                pApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
            }
            else
            {
                pApplicationName = config["applicationName"];
            }
            ApplicationId = GetApplicationId(pApplicationName);

            if (config["writeExceptionsToEventLog"] != null)
            {
                if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE")
                {
                    pWriteExceptionsToEventLog = true;
                }
            }



        }

        protected abstract int GetApplicationId(string applicationName);
        #endregion
        //
        // WriteToEventLog
        //   A helper function that writes exception detail to the event log. Exceptions
        // are written to the event log as a security measure to avoid private database
        // details from being returned to the browser. If a method does not return a status
        // or boolean indicating the action succeeded or failed, a generic exception is also 
        // thrown by the caller.
        //

        protected void WriteToEventLog(Exception e, string action)
        {
            EventLog log = new EventLog();
            log.Source = eventSource;
            log.Log = eventLog;

            string message = exceptionMessage + "\n\n";
            message += "Action: " + action + "\n\n";
            message += "Exception: " + e.ToString();

            log.WriteEntry(message);
        }

        #region Implementation of inherited abstract methods
        public abstract override void AddUsersToRoles(string[] usernames, string[] roleNames);
        public abstract override void CreateRole(string roleName);
        public abstract override bool DeleteRole(string roleName, bool throwOnPopulatedRole);
        public abstract override string[] FindUsersInRole(string roleName, string usernameToMatch);
        public abstract override string[] GetAllRoles();
        public abstract override string[] GetRolesForUser(string username);
        public abstract override string[] GetUsersInRole(string roleName);
        public abstract override bool IsUserInRole(string username, string roleName);
        public abstract override void RemoveUsersFromRoles(string[] usernames, string[] roleNames);
        public abstract override bool RoleExists(string roleName);
        #endregion
    }
}
